/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.increment;

import com.inspur.edp.cef.designtime.api.element.increment.GspCommonFieldIncrement;
import com.inspur.edp.cef.designtime.api.element.increment.ModifyFieldIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.CommonEntityIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.ModifyEntityIncrement;
import com.inspur.edp.cef.designtime.api.increment.IncrementType;
import com.inspur.edp.cef.designtime.api.increment.property.PropertyIncrement;
import com.inspur.edp.das.commonmodel.entity.GspCommonModel;
import com.inspur.edp.das.commonmodel.entity.increment.CommonModelIncrement;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.controlrule.rule.VoControlRule;
import com.inspur.edp.formserver.viewmodel.controlrule.rule.convert.VoControlRuleConvertor;
import com.inspur.edp.formserver.viewmodel.controlrule.ruledefine.VoControlRuleDef;
import com.inspur.edp.formserver.viewmodel.increment.ViewModelIncrement;
import com.inspur.edp.formserver.viewmodel.increment.extract.ViewModelExtractor;
import com.inspur.edp.formserver.viewmodel.increment.merger.ViewModelMerger;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.metadata.rtcustomization.api.AbstractCustomizedContent;
import com.inspur.edp.metadata.rtcustomization.spi.CustomizationExtHandler;
import com.inspur.edp.metadata.rtcustomization.spi.args.*;

import java.util.HashMap;
import java.util.Map;

public class ViewModelExtHandler implements CustomizationExtHandler {

    @Override
    public AbstractCustomizedContent getExtContent(ExtContentArgs args) {
        GspMetadata oldMetadata = args.getBasicMetadata();
        GspMetadata newMetadata = args.getExtMetadata();
        if(oldMetadata == null)
            throw new RuntimeException("增量抽取时，更新前的元数据为空");
        if(newMetadata == null)
            throw new RuntimeException("增量抽取时，更新后的元数据为空");
        ViewModelExtractor extractor =new ViewModelExtractor();
        GspViewModel oldVo = (GspViewModel)oldMetadata.getContent();
        GspViewModel newVo = (GspViewModel)newMetadata.getContent();

        VoControlRuleDef def = new VoControlRuleDef();
        VoControlRule rule = new VoControlRule();
        VoControlRuleConvertor.convert2ControlRule(def, rule, oldVo);

        return extractor.extract(oldVo, newVo, rule, def);
    }

    @Override
    public GspMetadata merge(MetadataMergeArgs args) {

        GspMetadata extendMetadata = args.getExtendMetadata();
        AbstractCustomizedContent baseIncrement = args.getCustomizedContent();
        GspMetadata metadata = (GspMetadata)extendMetadata.clone();
        if(metadata == null)
            throw new RuntimeException("增量合并时，扩展元数据为空");
        ViewModelMerger merger = new ViewModelMerger(true);
//        GspViewModel extendVo = (GspViewModel)metadata.getContent();
        GspViewModel extendVo = ((GspViewModel)extendMetadata.getContent()).clone();

        VoControlRuleDef def = new VoControlRuleDef();
        VoControlRule rule = new VoControlRule();

        GspMetadata baseVoMetadata =  args.getRootMetadata();

        VoControlRuleConvertor.convert2ControlRule(def, rule, (GspViewModel)baseVoMetadata.getContent());

        ViewModelIncrement extendIncrement = null;
//        ViewModelIncrement extendIncrement = (ViewModelIncrement)service.getChangeset(metadata.getHeader().getId() ,null, null);
        GspViewModel mergedVo = (GspViewModel)merger.merge(extendVo, (GspCommonModel) args.getRootMetadata().getContent(), extendIncrement == null ? new ViewModelIncrement():extendIncrement, (ViewModelIncrement)baseIncrement, rule, def);
        metadata.setContent(mergedVo);

        return metadata;
    }

    @Override
    public AbstractCustomizedContent getExtContent4SameLevel(Compare4SameLevelArgs args) {
        GspMetadata oldMetadata = args.getOldMetadata();
        GspMetadata newMetadata = args.getMetadata();
        if(oldMetadata == null)
            throw new RuntimeException("增量抽取时，更新前的元数据为空");
        if(newMetadata == null)
            throw new RuntimeException("增量抽取时，更新后的元数据为空");

        ViewModelExtractor extractor =new ViewModelExtractor(!oldMetadata.isExtended());
        GspViewModel oldVo = (GspViewModel)oldMetadata.getContent();
        GspViewModel newVo = (GspViewModel)newMetadata.getContent();

        VoControlRuleDef def = new VoControlRuleDef();
        VoControlRule rule = new VoControlRule();
        VoControlRuleConvertor.convert2ControlRule(def, rule, oldVo);

        return extractor.extract(oldVo, newVo, rule, def);
    }

    //region changeMerge
    @Override
    public AbstractCustomizedContent changeMerge(ChangeMergeArgs changeMergeArgs) {
        CommonModelIncrement parentChange = (CommonModelIncrement)changeMergeArgs.getParentChage();
        CommonModelIncrement extendChange = (CommonModelIncrement)changeMergeArgs.getChangeToParent();

        if(extendChange == null)
            return parentChange;
        mergeChangeProperties(parentChange.getChangeProperties(), extendChange.getChangeProperties());

        if(extendChange.getMainEntityIncrement() != null && parentChange.getMainEntityIncrement() != null)
            mergeObjectIncrement(parentChange.getMainEntityIncrement(), extendChange.getMainEntityIncrement());

        return parentChange;
    }


    private void mergeObjectIncrement(ModifyEntityIncrement parentIncrement, ModifyEntityIncrement extendIncrement){

        mergeChangeProperties(parentIncrement.getChangeProperties(), extendIncrement.getChangeProperties());

        for(Map.Entry<String, CommonEntityIncrement> childPair : parentIncrement.getChildEntitis().entrySet()){
            if(childPair.getValue().getIncrementType() != IncrementType.Modify)
                continue;
            if(extendIncrement.getChildEntitis().containsKey(childPair.getKey()))
                mergeObjectIncrement((ModifyEntityIncrement)childPair.getValue(), (ModifyEntityIncrement)extendIncrement.getChildEntitis().get(childPair.getKey()));
        }

        for(Map.Entry<String, GspCommonFieldIncrement> elePair : parentIncrement.getFields().entrySet()){
            GspCommonFieldIncrement fieldIncrement = elePair.getValue();
            if(fieldIncrement.getIncrementType() != IncrementType.Modify)
                continue;
            HashMap<String, GspCommonFieldIncrement> extendFields = extendIncrement.getFields();
            if(extendFields.containsKey(elePair.getKey())){
                mergeElementIncrement((ModifyFieldIncrement)fieldIncrement, (ModifyFieldIncrement)extendFields.get(elePair.getKey()));
            }
        }

    }

    private void mergeElementIncrement(ModifyFieldIncrement parentIncrement, ModifyFieldIncrement extendIncrement){
        mergeChangeProperties(parentIncrement.getChangeProperties(), extendIncrement.getChangeProperties());
    }

    private void mergeChangeProperties(HashMap<String, PropertyIncrement> parentChanges, HashMap<String, PropertyIncrement> extendChanges){
        for(Map.Entry<String, PropertyIncrement> changePair : extendChanges.entrySet()){
            if(parentChanges.containsKey(changePair.getKey())){
                parentChanges.remove(changePair.getKey());
            }
        }
    }

    //endregion

}
